﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

using TFSClient = Microsoft.TeamFoundation.WorkItemTracking.Client;

using LeMigue.Scrum.Iterface.Service;
using LeMigue.Scrum.Iterface.Model;
using LeMigue.Scrum.TfsScrumV1.Utils;


namespace LeMigue.Scrum.TfsScrumV1.Service
{
    public class SprintService : AbstractTfsService, ISprintService
    {

        private ITaskService _TaskService = new TaskService();
        private IItemBacklogService _BacklogService = new BacklogService();
        private IBugService _BugService = new BugService();
        private IIterationService _IterationService = new IterationService();

        private WorkItemFields[] QuerySelect = new WorkItemFields[]{
                WorkItemFields.StartDate,
                WorkItemFields.FinishDate,
                WorkItemFields.TeamProject
            };

        public SprintService()
        {
            
        }

        public IList<Sprint> List(Team team)
        {
            TfsQueryItem query = new TfsQueryItem(QuerySelect);

            query.AppendOrder(WorkItemFields.StartDate, false);

            query.AppendWhere(WorkItemFields.TeamProject, "=", team.Title)
                 .AppendWhere(" AND ").AppendWhere(WorkItemFields.WorkItemType, "=", WorkItemType.Sprint.ToString());


            TFSClient.WorkItemCollection retVal = GetItens(query);

            IList<Sprint> sprintes = new List<Sprint>();
            foreach (TFSClient.WorkItem item in retVal)
            {
                Sprint sprint =  item.ConvertToScrumItem<Sprint>(CreateSprint);
                sprintes.Add(sprint);
            }

            return sprintes;
        }

        public Sprint Load(int id)
        {
            return GetItem(id).ConvertToScrumItem<Sprint>(CreateSprint);
        }

        public Sprint Save(Sprint item)
        {

            Save(item.ConvertToWorkItem<Sprint>(GetItem(item.Id),SaveSprint));

            return item;
        }

        #region workitem

        protected Sprint CreateSprint(TFSClient.WorkItem w, Sprint item)
        {
            item.Start = w.Fields[WorkItemFields.StartDate.ToString()].Value != null ? (DateTime?)w.Fields[WorkItemFields.StartDate.ToString()].Value : null;
            item.End = w.Fields[WorkItemFields.FinishDate.ToString()].Value != null ? (DateTime?)w.Fields[WorkItemFields.FinishDate.ToString()].Value : null;

            //TODO: melhorar esta parte, acho q vai dar problema em algum lugar por esta referencia cruzada q não vale muito
            //TODO: está tentando carregar uma iteração que não existe mais nos nós (algum sprint que talvez não exista mais)
            TFSClient.Node no = w.Project.IterationRootNodes.GetNode(w.IterationId);
            if (no != null)
            {
                item.Iteration = new Iteration(no.Id, no.Name);
                item.Iteration.Sprint = item;
                item.Title = item.Iteration.Title;
            }

            item.SetTasks(new System.Lazy<IList<Task>>(() => _TaskService.List(item)));
            item.SetBacklogs(new System.Lazy<IList<ItemBacklog>>(() => _BacklogService.List(item)));
            item.SetBugs(new System.Lazy<IList<Bug>>(() => _BugService.List(item)));

            return item;
        }

        protected TFSClient.WorkItem SaveSprint(Sprint item, TFSClient.WorkItem w)
        {
            return w;
        } 
        #endregion

        public Sprint SprintByIteration(Iteration iteracao)
        {
            TfsQueryItem query = new TfsQueryItem(QuerySelect);

            query.AppendOrder(WorkItemFields.StartDate, false);

            query.AppendWhere(WorkItemFields.IterationId, "=", iteracao.Id)
                 .AppendWhere(" AND ").AppendWhere(WorkItemFields.WorkItemType, "=", WorkItemType.Sprint.ToString());


            TFSClient.WorkItemCollection retVal = GetItens(query);

            if (retVal.Count <= 0)
                return null;

            IList<Sprint> sprintes = new List<Sprint>();
            foreach (TFSClient.WorkItem item in retVal)
            {
                Sprint sprint = item.ConvertToScrumItem<Sprint>(CreateSprint);


                sprintes.Add(sprint);
            }
            Sprint unico = (Sprint)sprintes[0];

            if (sprintes.Count > 1)
            {
                //caso venha mais do que 1 dara a preferencia para o que tem data relacionada
                Sprint comdata = (Sprint)sprintes.SingleOrDefault(s => s.Start != null || s.End != null);
                if (comdata != null)
                {
                    unico = comdata;
                }
            }
            return unico;

        }

    }
}
